﻿using System;
using System.Text;
using S7.Net;

namespace NewUI.Service.Common;

public class PlcJuanCaiService
{
    public readonly Plc _plc;
    public bool IsConnected;
    private const int DbBlock = 129;
    private const int StructSize = 636; // 结构体大小

    public PlcJuanCaiService(string ipAddress)
    {
        _plc = new Plc(CpuType.S71500,ipAddress, 0,1);
    }

    public bool Connect()
    {
        if (IsConnected)
        {
            return IsConnected;
        }
        try
        {
            _plc.Open();
            IsConnected = true;
        }
        catch (Exception e)
        {
            Console.WriteLine(e);
        }
        
        return IsConnected;
    }

    public void Disconnect()
    {
        _plc.Close();
        IsConnected = false;
    }

    public PlcJuanCaiInfo ReadJuanCaiData(int dbOffset)
    {
        if (!Connect())
        {
            return null;
        }
        try
        {
            // 读取DB129从0开始的636字节
            // 使用辅助方法将名称转为编号（每次调用）
            byte[] content = _plc.ReadBytes(DataType.DataBlock, DbBlock, dbOffset, StructSize);
            PlcJuanCaiInfo data = new PlcJuanCaiInfo();
            data.ParseSource(content);
            return data;
        }
        catch (Exception ex)
        {
            Console.WriteLine($@"读取卷材数据时出错: {ex.Message}");
            return null;
        }
    }
    
    public bool WriteJuanCaiData(PlcJuanCaiInfo data, int dbOffset = 0)
    {
        if (!Connect()) return false;

        try
        {
            byte[] buffer = new byte[StructSize];
            ConvertToBytes(data, buffer);
            _plc.WriteBytes(DataType.DataBlock, DbBlock, dbOffset, buffer);
            return true;
        }
        catch (Exception ex)
        {
            Console.WriteLine($@"写入卷材数据时出错: {ex.Message}");
            return false;
        }
    }

    private void ConvertToBytes(PlcJuanCaiInfo data, byte[] buffer)
    {
        // 写入数值字段 (大端序)
        WriteInt32(data.Id, buffer, 0);
        WriteInt16(data.HouDu, buffer, 36);
        WriteInt16(data.ChangDu, buffer, 38);
        WriteInt16(data.KuanDu, buffer, 40);
        WriteInt16(data.ZhiJiang, buffer, 42);
        WriteInt16(data.DJ_class, buffer, 236);
        WriteInt16(data.From_SSD_No, buffer, 626);
        WriteInt16(data.TuoPan_No, buffer, 628);
        
        // 写入浮点数 (大端序)
        byte[] floatBytes = BitConverter.GetBytes(data.KuanDu_Add);
        Array.Reverse(floatBytes); // 转为大端序
        Array.Copy(floatBytes, 0, buffer, 632, 4);
        
        // 写入字符串字段
        WriteS7String(data.BianHao, Encoding.ASCII, 30, buffer, 4);
        WriteS7String(data.Treatment, Encoding.BigEndianUnicode, 30, buffer, 44);
        WriteS7String(data.ZhongLiang, Encoding.BigEndianUnicode, 30, buffer, 108);
        WriteS7String(data.DengJi, Encoding.BigEndianUnicode, 30, buffer, 174);
        WriteS7String(data.JianYanYuan, Encoding.BigEndianUnicode, 30, buffer, 240);
        WriteS7String(data.RiQi, Encoding.BigEndianUnicode, 30, buffer, 304);
        WriteS7String(data.Code, Encoding.BigEndianUnicode, 30, buffer, 368);
        WriteS7String(data.PiCi, Encoding.BigEndianUnicode, 30, buffer, 432);
        WriteS7String(data.Print_Template, Encoding.BigEndianUnicode, 30, buffer, 498);
        WriteS7String(data.KeHu_Name, Encoding.BigEndianUnicode, 30, buffer, 562);
        
        // 写入布尔字段
        buffer[494] = data.No_Pack ? (byte)1 : (byte)0;
        buffer[630] = data.HunBai ? (byte)1 : (byte)0;
        
        // 字节 624 的布尔字段
        buffer[624] = 0;
        if (data.KH_OK) buffer[624] |= 0x01;
        if (data.Print_Top_OK) buffer[624] |= 0x02;
        if (data.Print_Body_OK) buffer[624] |= 0x04;
        if (data.Need_QPM) buffer[624] |= 0x08;
        if (data.Need_ZG) buffer[624] |= 0x10;
        if (data.Need_PMD) buffer[624] |= 0x20;
        if (data.IS_HouPMD) buffer[624] |= 0x40;
        if (data.Double_PMD) buffer[624] |= 0x80;
        
        // 字节 625 的布尔字段
        buffer[625] = 0;
        if (data.Need_TieBiao_CM) buffer[625] |= 0x01;
        if (data.Need_TieBiao_Middle) buffer[625] |= 0x02;
        if (data.Multi_MiddleTieBiao) buffer[625] |= 0x04;
        if (data.LM_OK) buffer[625] |= 0x08;
        if (data.RR_OK) buffer[625] |= 0x10;
        if (data.DZ_Tetect_OK) buffer[625] |= 0x20;
    }

    private void WriteInt32(int value, byte[] buffer, int offset)
    {
        byte[] bytes = BitConverter.GetBytes(value);
        Array.Reverse(bytes); // 转为大端序
        Array.Copy(bytes, 0, buffer, offset, 4);
    }

    private void WriteInt16(short value, byte[] buffer, int offset)
    {
        byte[] bytes = BitConverter.GetBytes(value);
        Array.Reverse(bytes); // 转为大端序
        Array.Copy(bytes, 0, buffer, offset, 2);
    }

    private void WriteS7String(
        string value, 
        Encoding encoding,
        int maxLength,
        byte[] buffer,
        int startOffset)
    {
        if (string.IsNullOrEmpty(value))
            return;

        // 计算实际写入长度（不超过最大长度）
        int actualLength = Math.Min(value.Length, maxLength);
        int byteCount = encoding == Encoding.ASCII 
            ? actualLength 
            : actualLength * 2;

        // 写入字符串头信息（最大长度和实际长度）
        buffer[startOffset] = (byte)maxLength;
        buffer[startOffset + 1] = (byte)actualLength;

        // 编码字符串内容
        byte[] encodedBytes = encoding.GetBytes(value);
        int bytesToCopy = Math.Min(byteCount, encodedBytes.Length);
        Array.Copy(encodedBytes, 0, buffer, startOffset + 2, bytesToCopy);
    }
}